import java.lang.Math;

public class Tilecoder {
	
	final static int numOfTilings = 8;
	final static double tileWidth = 0.6;
	final static int gridDim = 11; // use an 11x11 grid
	final static int numFeatures = gridDim * gridDim * numOfTilings;

    /**
     * take inputs x1, x2 and array tilecodeIndices, and fill
     * tilecodeIndices with the indices of tiles where (x1,x2)
     * fall within. Entries in tilecodeIndices indicate elements
     * i of the feature vector phi where phi(i) = 1.
     */
	public static void tilecode(double x1, double x2, int[] tilecodeIndices) {
		
		int row;
		int col;
		int index;
		double offset = 0.0;
		
		for ( int tiling = 0; tiling < numOfTilings; tiling++ ) {
			
            // each successive tiling is offset by tileWidth/numOfTilings
			offset = (double) tiling * ( tileWidth / (double) numOfTilings );
			
            // find the row and column (x1,x2) falls within in this tiling
			row = (int) Math.floor( (x1 + offset) / tileWidth );
			col = (int) Math.floor( (x2 + offset) / tileWidth );
			
            // index is "x1-majored", each tiling contains a
            // successive range of indices
			index = row + col * gridDim + gridDim * gridDim * tiling;
			tilecodeIndices[tiling] = index;
			
		}
		
	}

	public static void main(String[] args) {
		int[] tilecodeIndices = new int[numOfTilings];

		printTileCoderIndices(0.1, 0.1, tilecodeIndices);
		printTileCoderIndices(4.0, 2.0, tilecodeIndices);
		printTileCoderIndices(5.99, 5.99, tilecodeIndices);
		printTileCoderIndices(4.0, 2.1, tilecodeIndices);
		
	}

	private static void printTileCoderIndices(double x1, double x2, int[] tilecodeIndices) {
		tilecode(x1, x2, tilecodeIndices);
		System.out.print("Tile indices for input (" + x1 + ", " + x2 + ") are: ");
		for (int i = 0; i < numOfTilings; i++)
			System.out.print(tilecodeIndices[i] + " ");
		System.out.println();
	}
}
